package com.ztools.wx.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.ztools.wx.async.WxMpAsyncTasks;
import com.ztools.wx.config.WxSysConstants;
import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.concurrent.TimeUnit;

import static com.ztools.common.util.wx.RedisUtil.CACHE_WX_USER_PREFIX;
import static com.ztools.wx.config.WxSysConstants.COOKIE_OPENID;

/**
 * @Author:seeTools
 * @Date: 2023/4/15  14:23
 * @Version 1.0
 */
@AllArgsConstructor
@Controller
public class WxOAuth2Controller {

    protected final Logger log = LoggerFactory.getLogger(getClass());
    private final WxMpService wxMpService;
    private final StringRedisTemplate stringRedisTemplate;
    private final WxMpAsyncTasks wxMpAsyncTasks;


    @GetMapping("/authorize")
    public String authorize(@RequestParam("returnUrl") String returnUrl) {
        // 回调方法
        String url = WxSysConstants.WX_SERVER_URL + "/userInfo";
        // 构造网页授权url
        String redirectUrl = wxMpService.getOAuth2Service().buildAuthorizationUrl(url, WxConsts.OAuth2Scope.SNSAPI_BASE, URLEncoder.encode(returnUrl));
        log.info("微信网页授权获取code，redirectUrl={}", redirectUrl);
        return "redirect:" + redirectUrl;
    }

    @GetMapping("/userInfo")
    public String userInfo(HttpServletRequest request, HttpServletResponse response, @RequestParam("code") String code, @RequestParam("state") String returnUrl) throws UnsupportedEncodingException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        WxOAuth2AccessToken accessToken;
        String openId = "";
        //判断cookie中是否存在openid，存在则直接返回，不存在则先获取再存进cookie
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (COOKIE_OPENID.equals(cookie.getName())) {
                    openId = cookie.getValue();
                }
            }
        }
        if (StrUtil.isEmpty(openId)) {
            try {
                accessToken = wxMpService.getOAuth2Service().getAccessToken(code);
                if (accessToken != null) {
                    openId = accessToken.getOpenId();
                }
            } catch (WxErrorException e) {
                e.printStackTrace();
            }
            // 把openid写入cookie中
            Cookie userCookie = new Cookie(COOKIE_OPENID, openId);
            userCookie.setMaxAge(60 * 60 * 24 * 30);
            userCookie.setPath("/");
            response.addCookie(userCookie);
        }
        return "redirect:" + returnUrl;
    }


    @RequestMapping(value = "/oauth2Code")
    public String oauth2Code(@RequestParam String returnUrl) {
        //重定向地址
        String redirectUrl = "";
        //授权验证跳转地址
        String backUrl = WxSysConstants.WX_SERVER_URL + "/oauth2Info?oauth2url=" + returnUrl;
        if (returnUrl != null) {
            //组装授权url
            redirectUrl = wxMpService.getOAuth2Service().buildAuthorizationUrl(backUrl, WxConsts.OAuth2Scope.SNSAPI_USERINFO, "loveAndPeace");
        }
        return "redirect:" + redirectUrl;
    }

    @RequestMapping(value = "/oauth2Info")
    public String oauth2Info(HttpServletRequest request, HttpServletResponse response, @RequestParam String code, @RequestParam String oauth2url) throws UnsupportedEncodingException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        if (!"authdeny".equals(code)) {
            WxOAuth2AccessToken accessToken;
            try {
                accessToken = wxMpService.getOAuth2Service().getAccessToken(code);
                if (accessToken != null) {
                    // 获取该用户的信息
                    WxOAuth2UserInfo userInfo = wxMpService.getOAuth2Service().getUserInfo(accessToken, null);
                    log.debug("获取到的用户信息为:{}", userInfo);
                    // 把用户信息存到redis缓存中
                    WxMpUser wxMpUser = new WxMpUser();
                    wxMpUser.setOpenId(userInfo.getOpenid());
                    wxMpUser.setHeadImgUrl(userInfo.getHeadImgUrl());
                    wxMpUser.setNickname(userInfo.getNickname());
                    wxMpUser.setUnionId(userInfo.getUnionId());
                    wxMpUser.setCity(userInfo.getCity());
                    wxMpUser.setProvince(userInfo.getProvince());
                    wxMpUser.setCountry(userInfo.getCountry());
                    stringRedisTemplate.opsForValue().set(CACHE_WX_USER_PREFIX + userInfo.getOpenid(), JSONUtil.toJsonStr(wxMpUser), 7L, TimeUnit.DAYS);
                    Cookie userOpenIdCookie = new Cookie(COOKIE_OPENID, userInfo.getOpenid());
                    userOpenIdCookie.setMaxAge(60 * 60 * 24 * 30);
                    userOpenIdCookie.setPath("/");
                    response.addCookie(userOpenIdCookie);
                    wxMpAsyncTasks.updateMemberNickName(wxMpUser.getOpenId(), wxMpUser.getNickname());
                }
            } catch (WxErrorException e) {
                e.printStackTrace();
            }
        }
        return "redirect:" + oauth2url;
    }


}
